package com.fleafinder;

import java.util.HashMap;
import java.util.Map;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.fleafinder.entity.Market;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

public class MapScreenFragment extends SupportMapFragment implements
		LocationListener {

	private Map<Marker, Market> markerMarketIdMap = new HashMap<Marker, Market>(10);

	/**
	 * A reference to GoogleMap control that is being used.
	 */
	private GoogleMap mapView = null;

	private boolean finishedAddingMarkerToMap = false;

	private boolean cameraRepositioned = false;

	private LocationManager locationManager;

	private LayoutInflater inflater = null;

	private Marker userLocationMarker = null;
	private boolean didRequestLocationUpdate = false;
	private static int zoomLevel = 7;

	private View mapInfoView = null;
	private TextView mapInfoName = null, mapInfoAddress = null,
			mapInfoMarketType = null, mapInfoCity = null, mapInfoDate = null,
			mapInfoTime = null, mapInfoStande = null;

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		return super.onCreateView(inflater, container, savedInstanceState);
	}

	public MapScreenFragment() {
		// supportMapFragment = SupportMapFragment.newInstance();
	}

	public void updateUserCurrentLocation() {
		if (didRequestLocationUpdate) {
			return;
		}

		if (locationManager == null) {
			locationManager = (LocationManager) getActivity().getSystemService(
					Context.LOCATION_SERVICE);
		}

		if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {

			AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
			builder.setTitle("Fleafinder Map");
			builder.setMessage("Please enable GPS on your mobile.");
			builder.setPositiveButton("YES",
					new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
						}
					});
			builder.show();
		}

		Criteria criteria = new Criteria();
		String provider = locationManager.getBestProvider(criteria, false);

		if (provider != null && !provider.equals("")) {
			locationManager.requestLocationUpdates(provider, 5000, 20, this);
			didRequestLocationUpdate = true;
		} else {
			Log.i("Map: No Provider Found", "");
		}
	}

	@Override
	public void onResume() {
		super.onResume();

		DataCenter.getInstance().setMapScreenFragment(this);

		if (mapView == null) {
			mapView = getMap();
		}

		// TODO [FleaFinder] check case mapView = null when Google Play not
		// available (wrong date/time ... ) and show messages.

		updateUserCurrentLocation();

		mapView.setOnInfoWindowClickListener(new GoogleMap.OnInfoWindowClickListener() {

			@Override
			public void onInfoWindowClick(Marker marker) {
				DataCenter dc = DataCenter.getInstance();
				FragmentTransaction fragmentTransaction = getFragmentManager()
						.beginTransaction();

				Market market = markerMarketIdMap.get(marker);

				if (market != null) {
					MarketDetailsFragment fr = dc
							.getMarketDetailsFragmentForMap(dc
									.readMarkedInfo(market.getId()));

					if (fr.isFullyInitialized()) {
						fr.updateViewWithMarket(dc.readMarkedInfo(market
								.getId()));
					}
					
					// set this fragment is not a Root fragmnent of current Tab
					dc.setRootFragmentOfTab(false);
					
					String tag = CommonConstants.MAP_FRAGMENT;

					fragmentTransaction.replace(R.id.fragment_placeholder, fr,
							tag);
					fragmentTransaction.addToBackStack(tag);
					fragmentTransaction.commit();
				}
			}
		});

		inflater = (LayoutInflater) getActivity().getSystemService(
				Context.LAYOUT_INFLATER_SERVICE);
		mapView.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {

			@Override
			public View getInfoWindow(Marker marker) {
				return null;
			}

			@Override
			public View getInfoContents(Marker marker) {
				if (mapInfoView == null) {
					mapInfoView = inflater.inflate(R.layout.map_info_window,
							null);

					mapInfoName = (TextView) mapInfoView
							.findViewById(R.id.map_info_market_name);
					mapInfoAddress = (TextView) mapInfoView
							.findViewById(R.id.map_info_address);
					mapInfoMarketType = (TextView) mapInfoView
							.findViewById(R.id.map_info_market_type);
					mapInfoCity = (TextView) mapInfoView
							.findViewById(R.id.map_info_city);
					mapInfoDate = (TextView) mapInfoView
							.findViewById(R.id.map_info_date);
					mapInfoTime = (TextView) mapInfoView
							.findViewById(R.id.map_info_time);
					mapInfoStande = (TextView) mapInfoView
							.findViewById(R.id.map_info_stande);
				}

				Market m = markerMarketIdMap.get(marker);

				if (m == null) {
					return null;
				}

				mapInfoName.setText(m.getName());
				mapInfoAddress.setText(m.getRoad());
				mapInfoMarketType.setText(m.getMarketTypeName());
				mapInfoCity.setText(m.getZip() + " " + m.getCity());
				mapInfoDate.setText("d." + m.getDateFrom() + " - "
						+ m.getDateTo());
				mapInfoTime.setText("Tid: " + m.getStartAt() + " - "
						+ m.getEndAt());
				mapInfoStande.setText("Stande: " + m.getStande());

				return mapInfoView;
			}
		});

		if (finishedAddingMarkerToMap) {
			return;
		}

		updateMarketMarkersToMap(false);
	}

	public void updateMarketMarkersToMap(boolean removeOldMarkers) {

		if (removeOldMarkers) {
			mapView.clear();
			markerMarketIdMap.clear();
		}

		AsyncTask<String, Market, String> mapMarkerAsyncTask = new AsyncTask<String, Market, String>() {

			@Override
			protected String doInBackground(String... params) {
				DataCenter dc = DataCenter.getInstance();
				
				if(dc.getMarketListWithLoadedLocation() != null && dc.getMarketListWithLoadedLocation().isEmpty() && !dc.isLoadingMarketLocation()){
					if (dc.getTimesOfLoadingLocation() < CommonConstants.MAX_TIMES_LOADING_LOCATION) {
						dc.startThreadLoadingMarketLocation();

						Toast t = Toast.makeText(getActivity(), getResources()
								.getString(R.string.loading_market_location),
								Toast.LENGTH_LONG);
						t.setGravity(Gravity.CENTER_HORIZONTAL, 5, 5);
						t.show();
					}
				}

				int oldIndex = 0, size = 0;
				boolean done = false;

				while (dc.isLoadingMarketLocation() || !done) {

					done = !dc.isLoadingMarketLocation();

					size = dc.getMarketListWithLoadedLocation().size();

					for (int i = oldIndex; i < size; ++i) {
						publishProgress(dc.getMarketListWithLoadedLocation()
								.get(i));
					}
					oldIndex = size;

					try {
						Thread.sleep(CommonConstants.DEFAULT_SLEEP_TIME);
					} catch (InterruptedException ex) {
						Log.i(ex.getMessage(), "");
					}
				}
				
				if(dc.getMarketListWithLoadedLocation() != null && dc.getMarketListWithLoadedLocation().isEmpty() && !dc.isLoadingMarketLocation()){
					Toast t = Toast.makeText(getActivity(),
							getResources().getString(R.string.couldnot_load_market_location), Toast.LENGTH_LONG);
					t.setGravity(Gravity.CENTER_HORIZONTAL, 5, 5);
					t.show();
				}

				// cameraRepositioned = false;

				// Log.i("", "AsyncTaskMap; Size of locations = " +
				// dc.getMarketListWithLoadedLocation().size());
				return null;
			}

			@Override
			protected void onProgressUpdate(Market... values) {
				Market m = values[0];
				if (m == null) {
					return;
				}

				LatLng latlng = new LatLng(m.getLatitude(), m.getLongitude());

				Marker marker = mapView.addMarker(new MarkerOptions()
						.icon(BitmapDescriptorFactory
								.fromResource(R.drawable.purplemarker))
						.position(latlng).title(m.getName())
						.snippet(m.getRoad() + ", " + m.getCity()));

				if (!cameraRepositioned) {
					mapView.moveCamera(CameraUpdateFactory.newLatLngZoom(
							latlng, 15));
					mapView.animateCamera(
							CameraUpdateFactory.zoomTo(zoomLevel), 1000, null);
					cameraRepositioned = true;
				}

				markerMarketIdMap.put(marker, m);
			}

		};
		mapMarkerAsyncTask.execute((String[]) null);
	}

	@Override
	public void onLocationChanged(Location location) {

		// AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
		// builder.setTitle("Fleafinder Map");
		// builder.setMessage("Update new location.");
		// builder.setPositiveButton("YES",
		// new DialogInterface.OnClickListener() {
		// @Override
		// public void onClick(DialogInterface dialog, int which) {
		// }
		// });
		// builder.show();

		// if (!userLocationUpdated) {

		if (userLocationMarker != null) {
			userLocationMarker.remove();
		}

		LatLng latlng = new LatLng(location.getLatitude(),
				location.getLongitude());
		
//		DataCenter.getInstance().setDeviceCurrentLocation(latlng);

		userLocationMarker = mapView
				.addMarker(new MarkerOptions()
						.icon(BitmapDescriptorFactory
								.fromResource(R.drawable.redmarker))
						.position(latlng)
						.title(getResources().getString(
								R.string.your_current_location)));

		mapView.moveCamera(CameraUpdateFactory.newLatLngZoom(latlng, 15));
		mapView.animateCamera(CameraUpdateFactory.zoomTo(zoomLevel), 1000, null);
		cameraRepositioned = true;
		// }

		// userLocationUpdated = true;
	}

	@Override
	public void onProviderDisabled(String provider) {

	}

	@Override
	public void onProviderEnabled(String provider) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub

	}

	public void reset() {
		// if(mapView != null){
		// mapView.clear();
		// }

		// finishedAddingMarkerToMap = false;
		cameraRepositioned = false;
		// userLocationMarker = null;
	}
}